package ch.unisi.inf.pfii.teamwhite.risk.core.player;

/**
 * 
 * @author Matteo Bellan: bellanm@lu.unisi.ch
 * @author Andrea Michelotti: micheloa@lu.unisi.ch
 * @author Ranganathan Ramasubramanian: ramasubr@lu.unisi.ch
 * 
 */

import java.util.ArrayList;

import ch.unisi.inf.pfii.teamwhite.risk.buildings.Building;
import ch.unisi.inf.pfii.teamwhite.risk.buildings.DefensiveShield;
import ch.unisi.inf.pfii.teamwhite.risk.buildings.EldestCouncil;
import ch.unisi.inf.pfii.teamwhite.risk.buildings.SlaveryCamp;
import ch.unisi.inf.pfii.teamwhite.risk.buildings.TaxCenter;
import ch.unisi.inf.pfii.teamwhite.risk.core.AttackHandler;
import ch.unisi.inf.pfii.teamwhite.risk.core.Planet;
import ch.unisi.inf.pfii.teamwhite.risk.core.ships.Frigate;

public class Human extends Player {
	
	private Planet selectedPlanet;
	private AttackHandler attackHandler;
	private boolean lastMovement;
	
	private final ArrayList<HumanListener> listeners;

	public Human(final String name) {
		super(name, "Human");
		attackHandler = new AttackHandler();
		setLastMovement(false);
		listeners = new ArrayList<HumanListener>();
	}

//	Getters and setters
	public final Planet getSelectedPlanet() {
		return selectedPlanet;
	}
	
	public final void setSelectedPlanet(final Planet planet) {
		selectedPlanet = planet;
	}
	
	public final AttackHandler getAttackHandler() {
		return attackHandler;
	}
	
	public void setLastMovement(boolean lastMovement) {
		this.lastMovement = lastMovement;
	}

	public boolean isLastMovement() {
		return lastMovement;
	}
	
//	This method assign the two initial planets of a player
	public final void assignPlanets(final ArrayList<Planet> planets) {
		if(selectedPlanet == null){
			firePlanetNotAvailable();
		}else{
			String firstPlanet = selectedPlanet.getName();
			selectPlanet(planets, firstPlanet);
			conquerPlanet(selectedPlanet);
			if (getTerritory().size() == 1) {
				selectedPlanet.setCapital(true);
			}
			selectedPlanet.createShip();
			
			fireAssignedPlanet();
			selectedPlanet = null;
		}
	}
	
	public final void play(final ArrayList<Planet> planets, final String command, final int numberOfShips){}

//	This method allows the player to build a building on the selected planet.
	public final void build(final String building) {
		Building theBuildingToBuild = null;
		if(building ==  null){
		}
		if (building.equals("Slavery Camp")) {
			theBuildingToBuild = new SlaveryCamp();
			selectedPlanet.addBuilding(theBuildingToBuild);
			fireSlaveryCamp();
		} else if (building.equals("Tax Center")) {
			theBuildingToBuild = new TaxCenter();
			selectedPlanet.addBuilding(theBuildingToBuild);
			fireTaxCenter();
		} else if (building.equals("Defensive Shield")) {
			theBuildingToBuild = new DefensiveShield();
			selectedPlanet.addBuilding(theBuildingToBuild);
			fireDefensiveShield();
		} else if (building.equals("Eldest Council")) {
			theBuildingToBuild = new EldestCouncil();
			selectedPlanet.addBuilding(theBuildingToBuild);
			fireEldestCouncil();
		}
		fireShipChangement();
		firePlanetChangement();
	}
	

//	This method create a new ship in the selected planet and decrease the money of the player by the cost of a ship
	public final void buyShip() {
		if (getMoney() < Frigate.getCost()) {
		} else {
			selectedPlanet.createShip();
			setMoney(getMoney() - Frigate.getCost());
		}
		fireMoneyChangement();
		fireShipChangement();
		firePlanetChangement();
	}
	
//	This method allows the player to move his ships from a planet to a neighbour
	public final void moveShips(final String destinationPlanet, final int numberOfShips) {
		setLastMovement(false);
		int oldNumberOfShips = selectedPlanet.getShips().size();
		Planet destination = destinationPlanet(selectedPlanet.getNeighbours(), destinationPlanet);
		if (destination == null) {
			firePlanetNotAvailable();
			return;
		} else {
			moveShips(selectedPlanet, destination, numberOfShips);
			for (int i = 0; i < oldNumberOfShips - numberOfShips - 1; i++) {
				selectedPlanet.createShip();
			}
			if (!destination.getOwner().equals(selectedPlanet.getOwner())) {
				fireAttack();
				attackHandler.handleAttack(this, numberOfShips, destination.getShips().size() - numberOfShips, destination);
			} else {
				fireMoved();
				setLastMovement(true);
				fireShipChangement();
				fireTurnFinished();
			}
		}
		selectedPlanet = null;
		fireShipChangement();
	}
	
//	This method conquer a planet changing the owner and adding it to the Ai player territory
	public final void conquerPlanet(final Planet planet) {
		planet.setOwner(this);
		getTerritory().add(planet);
		fireConqueredPlanet(planet);
	}

//	This method select the planet and print trough the console the main characteristic of it
	public final void selectPlanet(final ArrayList<Planet> planets, final String planetName) {
		for (Planet planet : planets) {
			if (planetName.equals(planet.getName()) && (planet.getOwner().equals(this) || (planet.getOwner().getName().equals("Gaia") && isDuringAssignment()))) {
				selectedPlanet = planet;
			}
		}
		firePlanetChangement();
		fireMoneyChangement();
	}
	
//	This method checks if a given planet is a neighbour the origin planet
	public final Planet isANeighbour(final String planetName) {
		Planet destinationPlanet = null;
		for (Planet planet : selectedPlanet.getNeighbours()) {
			if (planetName.equals(planet.getName())) {
				destinationPlanet = planet;
			}
		}
		return destinationPlanet;
	}

//	This method finds the destination planet
	private final Planet destinationPlanet(final ArrayList<Planet> planets, final String planetName) {
		Planet destinationPlanet = null;
		for (Planet planet : planets) {
			if (planetName.equals(planet.getName())) {
				destinationPlanet = planet;
			}
		}
		return destinationPlanet;
	}
	
//	Listeners
	public final void addHumanListener(final HumanListener li){
		listeners.add(li);
	}
	
	public final void removeHumanListener(final HumanListener li){
		listeners.remove(li);
	}
	
//	Fire methods
	private final void fireAssignedPlanet(){
		for (final HumanListener li : listeners) {
			li.planetAssigned();
		}
	}
	
	private final void firePlanetNotAvailable(){
		for (final HumanListener li : listeners) {
			li.planetNotAvailable();
		}
	}
	
	private final void firePlanetChangement(){
		for (final HumanListener li : listeners) {
			li.planetChangement();
		}
	}
	
	private final void fireShipChangement(){
		for (final HumanListener li : listeners) {
			li.shipChangement();
		}
	}
	
	private final void fireMoneyChangement(){
		for (final HumanListener li : listeners) {
			li.moneyChangement();
		}
	}
	
	private final void fireTurnFinished(){
		for (final HumanListener li : listeners) {
			li.turnFinished();
		}
	}
	
	private final void fireConqueredPlanet(final Planet planet){
		for (final HumanListener li : listeners) {
			li.conqueredPlanet(planet);
		}
	}
	
	private final void fireAttack(){
		for (final HumanListener li : listeners) {
			li.attack();
		}
	}
	
	private final void fireMoved(){
		for (final HumanListener li : listeners) {
			li.moved();
		}
	}
	
	private final void fireSlaveryCamp(){
		for (final HumanListener li : listeners) {
			li.slaveryCamp();
		}
	}
	
	private final void fireDefensiveShield(){
		for (final HumanListener li : listeners) {
			li.defensiveShield();
		}
	}
	
	private final void fireTaxCenter(){
		for (final HumanListener li : listeners) {
			li.taxCenter();
		}
	}
	
	private final void fireEldestCouncil(){
		for (final HumanListener li : listeners) {
			li.eldestCouncil();
		}
	}
}
